/******************************************************************************
 * This file is part of libemb.
 *
 * libemb is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * libemb is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with libemb.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Project: Embedme
 * Author : FergusZeng
 * Email  : cblock@126.com
 * git	  : https://git.oschina.net/cblock/embedme
 * Copyright 2014~2020 @ ShenZhen ,China
*******************************************************************************/
#include "EventTimer.h"
#include "Tracer.h"
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

#define     TIMER_TICK_MS			100       /* 100ms */
namespace libemb{
EventTimer::EventTimer(DateTime absTime)
{
	m_absTime = absTime;
	m_isExpired = false;
	m_isAbsTimer = true;
}
EventTimer::EventTimer(int interval, int unit)
{
	m_interval = interval;
	m_unit = unit;
	m_isExpired = false;
	m_isAbsTimer = false;
}

EventTimer::~EventTimer()
{
	m_isExpired = true;
}

/* 复位定时器 */
int EventTimer::reset()
{
	if(m_isAbsTimer)
	{	
		m_absTime = m_absTime;
	}
	else
	{
		switch(m_unit)
		{
			case TIME_UNIT_MILLISECOND:
				m_timerMS = m_interval;
				break;
			case TIME_UNIT_SECOND:
				m_timerMS = m_interval*1000;
				break;
			case TIME_UNIT_MINUTE:
				m_timerMS = m_interval*60*1000;
				break;
			case TIME_UNIT_HOUR:
				m_timerMS = m_interval*60*60*1000;
				break;
			case TIME_UNIT_DAY:
				m_timerMS = m_interval*24*60*60*1000;
				break;
			default:
				return STATUS_ERROR;
		}
	}
	m_isExpired = false;
	return STATUS_OK;
}
/*定时器定时响应 */
void EventTimer::onTick(EventCenter* eventCenter)
{
	if(m_isExpired)
	{
		return;
	}
	if(m_isAbsTimer)
	{
        DateTime currTime = DateTime::currentDateTime(); 
		if ((currTime.hour() == m_absTime.hour()) &&
			(currTime.minute() == m_absTime.minute()) &&
			(currTime.second() == m_absTime.second()))
		{
			onTimer(eventCenter);
			m_isExpired = true;
			if(TIMER_TYPE_PERIODIC==m_type)
			{
				reset();
			}
		}
	}
	else
	{
		m_timerMS -= TIMER_TICK_MS;
		if(m_timerMS <= 0 )
		{
			onTimer(eventCenter);
			m_isExpired = true;
			if(TIMER_TYPE_PERIODIC==m_type)
			{
				reset();
			}
		}
	}
}

PeriodicTimer::PeriodicTimer(DateTime absTime, int event)
:EventTimer(absTime)
{
	m_event=event;
	m_type=TIMER_TYPE_PERIODIC;
}
PeriodicTimer::PeriodicTimer(int interval, int unit, int event)
:EventTimer(interval,unit)
{
	m_event=event;
	m_type=TIMER_TYPE_PERIODIC;
}

PeriodicTimer::~PeriodicTimer()
{
}

void PeriodicTimer::onTimer(EventCenter* eventCenter)
{
	Event evt(m_event);
	eventCenter->postEvent(evt);
}

OneShotTimer::OneShotTimer(DateTime absTime, int event)
:EventTimer(absTime)
{
	m_event=event;
	m_type=TIMER_TYPE_ONESHOT;
}
OneShotTimer::OneShotTimer(int interval, int unit, int event)
:EventTimer(interval,unit)
{
	m_event=event;
	m_type=TIMER_TYPE_ONESHOT;
}

OneShotTimer::~OneShotTimer()
{
}

void OneShotTimer::onTimer(EventCenter* eventCenter)
{
	Event evt(m_event);
	eventCenter->postEvent(evt);
}

EventTimerManager::EventTimerManager()
{
	m_timerThread.start(this);
}

EventTimerManager::~EventTimerManager()
{
	m_timerThread.cancel();
}

/**
 *  \brief  增加定时器
 *  \param  timer 定时器
 *  \return 成功返回STATUS_OK,失败返回STATUS_ERROR
 *  \note   none
 */
int EventTimerManager::addTimer(EventTimer* timer)
{
	AutoLock lock(&m_listLock);
	std::list<EventTimer*>::iterator iter;
	for(iter=m_timerList.begin(); iter!=m_timerList.end(); iter++)
	{
		if((*iter) == timer)
		{
			(*iter)->reset();
			return STATUS_OK;
		}
	}
	timer->reset();
	m_timerList.push_back(timer);
	return STATUS_OK;
}

/**
 *  \brief  移除定时器
 *  \param  timer 定时器
 *  \return 成功返回STATUS_OK,失败返回STATUS_ERROR
 *  \note   none
 */
int EventTimerManager::removeTimer(EventTimer* timer)
{
	AutoLock lock(&m_listLock);
	std::list<EventTimer*>::iterator iter;
	for(iter=m_timerList.begin(); iter!=m_timerList.end(); iter++)
	{
		if((*iter) == timer)
		{
			m_timerList.erase(iter);
			return STATUS_OK;
		}
	}
	return STATUS_OK;
}

/**
 *  \brief  重新启用定时器
 *  \param  timer 定时器
 *  \return 成功返回STATUS_OK,失败返回STATUS_ERROR
 *  \note   none
 */
int EventTimerManager::restartTimer(EventTimer* timer)
{
	AutoLock lock(&m_listLock);
	std::list<EventTimer*>::iterator iter;
	for(iter=m_timerList.begin(); iter!=m_timerList.end(); iter++)
	{
		if((*iter) == timer)
		{
			timer->reset();
			return STATUS_OK;
		}
	}
	return STATUS_OK;
}


/* 定时器管理者线程 */
void EventTimerManager::run()
{
	std::list<EventTimer*>::iterator iter;
	while(1)
	{
		Thread::msleep(TIMER_TICK_MS);
		m_listLock.lock();
		for(iter=m_timerList.begin(); iter!=m_timerList.end(); iter++)
		{
			(*iter)->onTick(this);
		}
		m_listLock.unLock();
	}
}


}